package com.ydtech.common.exception;

import com.ydtech.common.ResultUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by zhengping.zhu
 * on 2017/5/7.
 * 错误定义
 */
@ControllerAdvice
public class GlobalExceptionHandle {

    private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandle.class);

    /**
     * 判断错误是否是已定义的已知错误，不是则由未知错误代替，同时记录在log中
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Object exceptionGet(HttpServletRequest request, Exception e) {
        logger.error("【系统异常】{}", e);

        if (isAjaxRequest(request)) {
            if (e instanceof DescribeException) {
                DescribeException pingjiaException = (DescribeException) e;
                return ResultUtil.error(pingjiaException.getCode(), pingjiaException.getMessage());
            }

            ErrorInfo errorInfo = getErrorInfo(e);
            if (errorInfo != null) {
                return ResultUtil.error(-9999, "error", errorInfo);
            }

            return ResultUtil.error(ExceptionEnum.UNKNOW_ERROR);
        } else {
            ModelAndView modelAndView = new ModelAndView();

            ErrorInfo errorInfo = getErrorInfo(e);
            if (errorInfo != null) {
                modelAndView.addObject("errorInfo", errorInfo);
            } else {
                modelAndView.addObject("errorInfo", "没有详细信息，请与管理员联系");
            }
            modelAndView.setViewName("error");

            return modelAndView;
        }
    }

    private ErrorInfo getErrorInfo(Exception e) {
        if (e.getStackTrace() != null && e.getStackTrace().length > 0) {
            StackTraceElement element = e.getStackTrace()[0];
            ErrorInfo errorInfo = new ErrorInfo(
                    element.getClassName(),
                    element.getFileName(),
                    element.getMethodName(),
                    element.getLineNumber() + ""
            );

            return errorInfo;
        }

        return null;
    }

    /**
     * 是否是Ajax异步请求
     *
     * @param request
     */
    private boolean isAjaxRequest(HttpServletRequest request)
    {
        String accept = request.getHeader("accept");
        if (accept != null && accept.indexOf("application/json") != -1)
        {
            return true;
        }

        String xRequestedWith = request.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
        {
            return true;
        }

        String uri = request.getRequestURI();
        if (inStringIgnoreCase(uri, ".json", ".xml"))
        {
            return true;
        }

        String ajax = request.getParameter("__ajax");
        if (inStringIgnoreCase(ajax, "json", "xml"))
        {
            return true;
        }
        return false;
    }

    /**
     * 是否包含字符串
     *
     * @param str 验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    private boolean inStringIgnoreCase(String str, String... strs)
    {
        if (str != null && strs != null)
        {
            for (String s : strs)
            {
                if (str.equalsIgnoreCase((s == null ? "" : s.trim())))
                {
                    return true;
                }
            }
        }
        return false;
    }

}


